/**
 *Copyright (c) 2024 watereyes
 * workflow is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.workflow.common.util;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.koron.ebs.mybatis.ADOConnection;
import org.koron.ebs.mybatis.SessionFactory;
import org.koron.ebs.mybatis.SqlTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.google.gson.Gson;
import com.koron.workflow.applicationManag.bean.AppBean;
import com.koron.workflow.applicationManag.mapper.AppManagMapper;
import com.koron.workflow.baseConfig.mapper.StaffMapper;
import com.koron.workflow.common.bean.StaffBean;
import com.koron.workflow.common.exception.WorkflowException;
import com.koron.workflow.common.service.MailSendService;
import com.koron.workflow.common.service.MessageSendService;

/**
 * WorkflowUtil
 */
@Component
public class WorkflowUtil {
	
    private static String tokenSecret;
	
    private static String expireTime;
	
	private static MessageSendService messageSendService;
	
	private static MailSendService mailSendService;
	
    public static boolean sendMail(String toEmail, String content) {
    	return mailSendService.sendMail(toEmail, content);
    }
    
    public static boolean sendMessage(String mobile, String content) {
    	return messageSendService.sendMessage(mobile, content);
    }
    
    @Value("${token.secret}")
    public void setTokenSecret(String tokenSecret) {
		WorkflowUtil.tokenSecret = tokenSecret;
	}

	@Autowired
    public void setMessageSendService(MessageSendService messageSendService) {
    	WorkflowUtil.messageSendService = messageSendService;
	}

    @Autowired
	public void setMailSendService(MailSendService mailSendService) {
    	WorkflowUtil.mailSendService = mailSendService;
	}
    
    @Value("${token.expireTime}")
	public void setExpireTime(String expireTime) {
		WorkflowUtil.expireTime = expireTime;
	}

	/**
     * 获取 ObjectId
     * @return
     */
    public static String getObjectId() {
        return ObjectId.get().toHexString();
    }
    
    /**
     * 先从当前的 HttpServletRequest 请求头中获取token  
     * 在通过token 获取当前的用户信息
     * @return
     */
    public static StaffBean getStaff() {
    	HttpServletRequest request = getCurrentRequest();
    	String token = request.getHeader("token");
    	if(StringUtils.isBlank(token)) {
    		throw new WorkflowException(BusinessCode.FAILURE.getCode(), "请求头中参数不能为空");
    	}
		return getStaff(token);
    }
    
    public static AppBean getApp(String appCode) {
    	return ADOConnection.runTask(new SqlTask() {
			@Override
			public Object run(SessionFactory factory) {
				return factory.getMapper(AppManagMapper.class).queryByCode(appCode);
			}
		}, AppBean.class);
    }
    
    public static List<StaffBean> getStaffByCode(final List<String> code) {
    	return code.stream().map(t -> getStaffByCode(t)).collect(Collectors.toList());
    }
    
    public static StaffBean getStaffByCode(final String code) {
    	return ADOConnection.runTask(new SqlTask() {
			@Override
			public Object run(SessionFactory factory) {
				return factory.getMapper(StaffMapper.class).queryByCode(code);
			}
		}, StaffBean.class);
    }
    
    public static List<StaffBean> getStaffByAccount(final List<String> account) {
    	return account.stream().map(t -> getStaffByAccount(t)).collect(Collectors.toList());
    }
    
    public static StaffBean getStaffByAccount(final String account) {
    	return ADOConnection.runTask(new SqlTask() {
			@Override
			public Object run(SessionFactory factory) {
				return factory.getMapper(StaffMapper.class).queryByAccount(account);
			}
		}, StaffBean.class);
    }
    
    /**
     * 通过token获取当前的用户
     * @param token
     * @return
     */
    public static StaffBean getStaff(String token) {
    	 Object object = RedisUtils.get(token);
    	if(object == null) {
    		throw new WorkflowException(BusinessCode.NOT_LONGIN.getCode(), BusinessCode.NOT_LONGIN.getDescription());
    	}
    	 return new Gson().fromJson(object.toString(), StaffBean.class);
    }
    
    public static String setTokenCookie(HttpServletResponse response, StaffBean staff) {
		String token = getToken(staff);
        Cookie cookie = new Cookie("token", token);
        response.addCookie(cookie);
        RedisUtils.set(token, new Gson().toJson(staff), Integer.parseInt(expireTime));
    	return token;
    }
    
    public static StaffBean getStaff(HttpServletRequest request) {
    	 String token = request.getParameter("token");
         if (StringUtils.isEmpty(token)) {
             token = request.getHeader("token");
             if (StringUtils.isEmpty(token)) {
                 Cookie[] cookies = request.getCookies();
                 if (cookies != null && cookies.length > 0) {
                     for (Cookie cookie : cookies) {
                         if ("token".equals(cookie.getName())) {
                             token = cookie.getValue();
                             break;
                         }
                     }
                 }
             }
         }
         if (!StringUtils.isEmpty(token) && RedisUtils.hasKey(token)) {
        	 String object = RedisUtils.get(token);
        	 return new Gson().fromJson(object.toString(), StaffBean.class);
         }
         return null;
    }
    
    /**
     * 获取token
     * @param user
     * @return
     */
    public static String getToken(StaffBean user) {
        // 过期时间
        Date date = new Date(System.currentTimeMillis() + Long.valueOf(expireTime));
        // 私钥加密
        Algorithm algorithm = Algorithm.HMAC256(tokenSecret);
        return JWT.create()
                .withClaim("userCode", user.getCode())
                .withClaim("userName", user.getName())
                .withExpiresAt(date)
                .sign(algorithm);
    }
    
    public static HttpServletRequest getCurrentRequest() {
		return ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); 
	}
}
